package cn.studyjams.s1.contest.autohello;

import android.annotation.TargetApi;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.AppCompatSpinner;
import android.support.v7.widget.SwitchCompat;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.MultiAutoCompleteTextView;

import com.android.ex.chips.BaseRecipientAdapter;
import com.android.ex.chips.RecipientEditTextView;
import com.android.ex.chips.recipientchip.DrawableRecipientChip;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

import cn.studyjams.s1.contest.autohello.model.ColorPicker;
import cn.studyjams.s1.contest.autohello.model.Contact;
import cn.studyjams.s1.contest.autohello.model.Event;
import cn.studyjams.s1.contest.autohello.model.RepeatMode;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;

import static android.Manifest.permission.READ_CONTACTS;

public class AddEventActivity extends BaseActivity implements
        View.OnClickListener,
        AddTagFragment.AddTagListener,
        PreviewEventFragment.PreviewEventListener,
        DatePickerDialog.OnDateSetListener,
        TimePickerDialog.OnTimeSetListener,
        SetRepeatFragment.SetRepeatListener,
        SetColorFragment.SetColorListener,
        ChooseCityFragment.ChooseCityListener,
        AdapterView.OnItemSelectedListener {

    private final static String TAG = "AddEventActivity";

    private static final int SEND_SMS_PERMS = 201;
    private static final int REQUEST_READ_CONTACTS = 0;

    private ImageButton switchPhoneAndMailIBTN;

    private boolean isPhoneOrMailVisible = true; // phone visible

    private RecipientEditTextView receiverPhoneETV;
    private RecipientEditTextView receiverEmailETV;

    private EditText contentET;
    private Button dateTV;
    private Button timeTV;

    private Button repeatModeBTN;
    private RepeatMode mRepeatMode;

    private Button tagBTN;
    private Button colorBTN;
    private SwitchCompat isActiveSC;

    //----------------------------------------------
    //  Event value
    //----------------------------------------------

    private String mYear;
    private String mMonth;
    private String mDay;
    private String mWeek;

    private String mHour;
    private String mMinute;

    private Event mEvent;
    private int mEventType;

    private Double lat;
    private Double lon;

    private LinearLayout weatherPanel;
    private Button addWeatherContentBTN;
    private Button chooseCityBTN;
    private AppCompatSpinner weatherCFSP;
    private boolean isCF = true; // C摄氏度 = true;

    private int color = 5;

    public AddEventActivity() {
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_event);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);

        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            // Show the Up button in the action bar.
            actionBar.setHomeAsUpIndicator(R.drawable.ic_close_24dp);
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        weatherPanel = (LinearLayout) findViewById(R.id.weather_panel);
        addWeatherContentBTN = (Button) findViewById(R.id.add_weather_content);
        chooseCityBTN = (Button) findViewById(R.id.choose_city);
        weatherCFSP = (AppCompatSpinner) findViewById(R.id.weather_C_F);

        switchPhoneAndMailIBTN = (ImageButton) findViewById(R.id.switch_between_phone_and_email);

        receiverPhoneETV = (RecipientEditTextView) findViewById(R.id.receivers_phone);
        receiverEmailETV = (RecipientEditTextView) findViewById(R.id.receivers_email);

        contentET = (EditText) findViewById(R.id.content);
        dateTV = (Button) findViewById(R.id.date);
        timeTV = (Button) findViewById(R.id.time);
        repeatModeBTN = (Button) findViewById(R.id.repeatMode);
        tagBTN = (Button) findViewById(R.id.tag);
        colorBTN = (Button) findViewById(R.id.color);
        isActiveSC = (SwitchCompat) findViewById(R.id.is_active);

        switchPhoneAndMailIBTN.setOnClickListener(this);
        dateTV.setOnClickListener(this);
        timeTV.setOnClickListener(this);

        tagBTN.setOnClickListener(this);
        colorBTN.setOnClickListener(this);

        Calendar now = Calendar.getInstance();

        mYear = new SimpleDateFormat("yyyy", Locale.getDefault()).format(now.getTime());
        mMonth = new SimpleDateFormat("MM", Locale.getDefault()).format(now.getTime());
        mDay = new SimpleDateFormat("dd", Locale.getDefault()).format(now.getTime());

        mWeek = new SimpleDateFormat("E", Locale.getDefault()).format(now.getTime());

        mHour = new SimpleDateFormat("HH", Locale.getDefault()).format(now.getTime());
        mMinute = new SimpleDateFormat("mm", Locale.getDefault()).format(now.getTime());

        String date = String.format(getResources().getString(R.string.default_date_picker), mWeek, mMonth, mDay, mYear);
        dateTV.setText(date);
        String time = String.format(getResources().getString(R.string.default_time_picker), mHour, mMinute);
        timeTV.setText(time);

        populateContactList();

        // repeat mode
        mRepeatMode = new RepeatMode();

        mEventType = getIntent().getIntExtra("eventType", 0);

        initContentPanel();
    }

    private void initContentPanel() {
        switch (mEventType) {
            case 0:
                weatherPanel.setVisibility(View.GONE);
                repeatModeBTN.setOnClickListener(this);
                contentET.setHint(getString(R.string.write_something));
                break;
            case 1:
                // 天气预报
                addWeatherContentBTN.setOnClickListener(this);
                chooseCityBTN.setOnClickListener(this);
                weatherCFSP.setOnItemSelectedListener(this);
                repeatModeBTN.setOnClickListener(this);
                contentET.setHint(getString(R.string.nice_day));
                break;
            case 2:
                // 生日祝福，不能选择重复（默认每年一次）
                repeatModeBTN.setText(getString(R.string.repeat_every_year));
                mRepeatMode = new RepeatMode();
                mRepeatMode.setRepeatType(4);
                weatherPanel.setVisibility(View.GONE);
                contentET.setHint(getString(R.string.birthday_wishes));
                break;
            case 3:
                //节日问候，不能选择重复（默认每年一次）
                repeatModeBTN.setText(getString(R.string.repeat_every_year));
                mRepeatMode = new RepeatMode();
                mRepeatMode.setRepeatType(4);
                weatherPanel.setVisibility(View.GONE);
                contentET.setHint(getString(R.string.merry_christmas));
                break;
        }
    }


    public void populateContactList() {
        if (!mayRequestContacts()) {
            return;
        }

        // autocomplete contacts phone number
        receiverPhoneETV.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
        BaseRecipientAdapter adapter = new BaseRecipientAdapter(BaseRecipientAdapter.QUERY_TYPE_PHONE, this);
        adapter.setShowMobileOnly(false);
        receiverPhoneETV.setAdapter(adapter);
        receiverPhoneETV.dismissDropDownOnItemSelected(true);

        // creates an autocomplete for email contacts
        receiverEmailETV.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
        receiverEmailETV.setAdapter(new BaseRecipientAdapter(BaseRecipientAdapter.QUERY_TYPE_EMAIL, this));
        receiverEmailETV.dismissDropDownOnItemSelected(true);
    }

    private boolean mayRequestContacts() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }
        if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
            Snackbar.make(receiverPhoneETV, R.string.rationale_read_contact, Snackbar.LENGTH_INDEFINITE)
                    .setAction(android.R.string.ok, new View.OnClickListener() {
                        @Override
                        @TargetApi(Build.VERSION_CODES.M)
                        public void onClick(View v) {
                            requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
                        }
                    });
        } else {
            requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
        }
        return false;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        if (requestCode == REQUEST_READ_CONTACTS) {
            if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                populateContactList();
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_add_event, menu);
        return true;
    }

    @AfterPermissionGranted(SEND_SMS_PERMS)
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        String perm = android.Manifest.permission.SEND_SMS;
        if (!EasyPermissions.hasPermissions(this, perm)) {
            EasyPermissions.requestPermissions(this, getString(R.string.rationale_send_sms),
                    SEND_SMS_PERMS, perm);
            return false;
        }

        if (item.getItemId() == R.id.action_save) {
            List<Contact> contacts = new ArrayList<>();

            DrawableRecipientChip[] mPhoneChips = receiverPhoneETV.getRecipients();
            DrawableRecipientChip[] mEmailChips = receiverEmailETV.getRecipients();

            for (DrawableRecipientChip chip : mPhoneChips) {
                Contact contact = new Contact(
                        chip.getEntry().getDisplayName(),
                        chip.getEntry().getDestination(),
                        "",
                        0
                );
                contacts.add(contact);
                Log.d(TAG, "phone:" + chip.getEntry().getDisplayName() + " " + chip.getEntry().getDestination());
            }

            for (DrawableRecipientChip chip : mEmailChips) {
                Contact contact = new Contact(
                        chip.getEntry().getDisplayName(),
                        "",
                        chip.getEntry().getDestination(),
                        1
                );
                contacts.add(contact);
                Log.d(TAG, "email:" + chip.getEntry().getDisplayName() + " " + chip.getEntry().getDestination());
            }

            // content
            String content = contentET.getText().toString();
            if (TextUtils.isEmpty(content)) {
                contentET.setError(getString(R.string.required));
                return true;
            } else {
                Log.d(TAG, "content:" + content);
            }

            if (sharedPref.getBoolean("additional_content", true)) {
                content += " " + getString(R.string.additional_content);
            }

            if (mEventType == 1) {
                if (lat == null || lon == null) {
                    Snackbar.make(
                            weatherPanel,
                            getString(R.string.choose_city_error),
                            Snackbar.LENGTH_LONG
                    ).show();
                    return true;
                }

                if (!content.contains(getString(R.string.weather_encode))) {
                    Snackbar.make(
                            weatherPanel,
                            String.format(
                                    getString(R.string.add_weather_encode_error),
                                    getString(R.string.weather_encode)
                            ),
                            Snackbar.LENGTH_LONG
                    ).show();
                    return true;
                }
            }

            //Datetime
            Calendar calendar = getCalendar(mRepeatMode);

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
            String dateStr = sdf.format(calendar.getTime());
            Log.d(TAG, "Datetime:" + dateStr);


            // RepeatMode
            Log.d(TAG, "RepeatMode:" + mRepeatMode.getRepeatType());

            //label
            String tag = tagBTN.getText().toString();
            Log.d(TAG, "Label:" + tag);

            //color

            //isActive
            boolean isActive = isActiveSC.isChecked();
            Log.d(TAG, "isActive:" + isActive);

            mEvent = new Event(
                    UUID.randomUUID().toString(),
                    content,
                    contacts,
                    tag.equals(getString(R.string.add_tag)) ? "" : tag,
                    dateStr,
                    mRepeatMode,
                    color,
                    isActive,
                    mEventType,
                    System.currentTimeMillis(),
                    false
            );

            if (mEventType == 1) {
                mEvent.setLat(lat);
                mEvent.setLon(lon);
                mEvent.setIsCF(isCF);
            }

            Bundle bundle = new Bundle();
            bundle.putSerializable("event", mEvent);
            PreviewEventFragment previewEventFragment = new PreviewEventFragment();

            previewEventFragment.setArguments(bundle);
            previewEventFragment.show(getSupportFragmentManager(), "PREVIEW_EVENT");
        }

        return super.onOptionsItemSelected(item);
    }


    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.switch_between_phone_and_email:
                if (isPhoneOrMailVisible) {
                    receiverPhoneETV.setVisibility(View.GONE);
                    receiverEmailETV.setVisibility(View.VISIBLE);

                    isPhoneOrMailVisible = false;
                } else {
                    receiverPhoneETV.setVisibility(View.VISIBLE);
                    receiverEmailETV.setVisibility(View.GONE);

                    isPhoneOrMailVisible = true;
                }
                break;
            case R.id.date:
                DatePickerDialog datePickerDialog = DatePickerDialog.newInstance(
                        AddEventActivity.this,
                        Integer.parseInt(mYear),
                        Integer.parseInt(mMonth) - 1,
                        Integer.parseInt(mDay)
                );
                datePickerDialog.setVersion(DatePickerDialog.Version.VERSION_2);
                datePickerDialog.show(getFragmentManager(), "DATE_PICKER");
                break;
            case R.id.time:
                TimePickerDialog timePickerDialog = TimePickerDialog.newInstance(
                        AddEventActivity.this,
                        Integer.parseInt(mHour),
                        Integer.parseInt(mMinute),
                        true
                );
                timePickerDialog.setVersion(TimePickerDialog.Version.VERSION_2);
                timePickerDialog.show(getFragmentManager(), "TIME_PICKER");
                break;
            case R.id.repeatMode:
                SetRepeatFragment setRepeatFragment = new SetRepeatFragment();
                setRepeatFragment.setCancelable(false);
                setRepeatFragment.show(getSupportFragmentManager(), "REPEAT_MODE");
                break;
            case R.id.tag:
                Bundle bundle = new Bundle();
                String tagTemp = tagBTN.getText().toString();
                bundle.putString("tag", tagTemp.equals(getString(R.string.add_tag)) ? "" : tagTemp);
                AddTagFragment fragment = new AddTagFragment();
                fragment.setArguments(bundle);
                fragment.show(getSupportFragmentManager(), "TAG");
                break;
            case R.id.color:
                SetColorFragment setColorFragment = new SetColorFragment();
                setColorFragment.setCancelable(false);
                setColorFragment.show(getSupportFragmentManager(), "COLOR_PICKER");
                break;
            case R.id.add_weather_content:
                contentET.append(getString(R.string.weather_encode));
                break;
            case R.id.choose_city:
                ChooseCityFragment chooseCityFragment = new ChooseCityFragment();
                chooseCityFragment.show(getSupportFragmentManager(), "CHOOSE_CITY");
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onConfirmAddTag(String tag) {
        tagBTN.setText(tag);
    }

    @Override
    public void onCancelAddTag() {

    }

    @Override
    public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
        String dateStr = year + "-" + (monthOfYear + 1) + "-" + dayOfMonth;
        try {
            final Date date = dateFormat.parse(dateStr);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);

            mYear = new SimpleDateFormat("yyyy", Locale.getDefault()).format(calendar.getTime());
            mMonth = new SimpleDateFormat("MM", Locale.getDefault()).format(calendar.getTime());
            mDay = new SimpleDateFormat("dd", Locale.getDefault()).format(calendar.getTime());

            mWeek = new SimpleDateFormat("E", Locale.getDefault()).format(calendar.getTime());

            String str = String.format(getResources().getString(R.string.default_date_picker), mWeek, mMonth, mDay, mYear);
            dateTV.setText(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int second) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
        String dateStr = mYear + "-" + mMonth + "-" + mDay + " " + hourOfDay + ":" + minute;

        final Date date;
        try {
            date = dateFormat.parse(dateStr);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);

            mHour = new SimpleDateFormat("HH", Locale.getDefault()).format(calendar.getTime());
            mMinute = new SimpleDateFormat("mm", Locale.getDefault()).format(calendar.getTime());

            String str = String.format(getResources().getString(R.string.default_time_picker), mHour, mMinute);
            timeTV.setText(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConfirmSetRepeat(RepeatMode repeatMode) {
        mRepeatMode = repeatMode;
        String repeatStr = "";
        switch (repeatMode.getRepeatType()) {
            case 0:
                repeatStr += getString(R.string.do_not_repeat);
                break;
            case 1:
                repeatStr += getString(R.string.repeat_every_day);
                break;
            case 2:
                repeatStr += getString(R.string.repeat_every_week);
                String weeksStr = repeatMode.getWhichWeeks();
                String[] whichWeeks = weeksStr.substring(1, weeksStr.length() - 1).split(", ");

                Map<Integer, String> weekMap = new HashMap<>();
                weekMap.put(0, getString(R.string.sun));
                weekMap.put(1, getString(R.string.mon));
                weekMap.put(2, getString(R.string.tue));
                weekMap.put(3, getString(R.string.wed));
                weekMap.put(4, getString(R.string.thu));
                weekMap.put(5, getString(R.string.fri));
                weekMap.put(6, getString(R.string.sat));

                weeksStr = "";
                for (int i = 0; i < 7; i++) {
                    if (whichWeeks[i].equals("true")) {
                        weeksStr += weekMap.get(i) + " ";
                    }
                }

                repeatStr += "; " + weeksStr;
                break;
            case 3:
                repeatStr += getString(R.string.repeat_every_month);
                if (repeatMode.getSameDayOrSameWeekOfTheMonth() == 0) {
                    repeatStr += "; " + getString(R.string.same_day);
                } else if (repeatMode.getSameDayOrSameWeekOfTheMonth() == 1) {
                    repeatStr += ";" + getString(R.string.same_week);
                }
                break;
            case 4:
                repeatStr += getString(R.string.repeat_every_year);
                break;
        }

        if (repeatMode.getEndCondition() == 1) {
            //直到某一个日期
            repeatStr += "; " + String.format(getString(R.string.end_condition_until), repeatMode.getEndDateTime());
        } else if (repeatMode.getEndCondition() == 2) {
            //直到一定次数
            repeatStr += "; " + String.format(getString(R.string.end_condition_for), repeatMode.getEndCounts() + "");
        }

        repeatModeBTN.setText(repeatStr);
    }

    @Override
    public void onConfirmSetColor(ColorPicker colorPicker) {
        colorBTN.setText(colorPicker.getColorName());
        color = colorPicker.getIndex();
    }

    @Override
    public void onConfirmSaveEvent() {
        if (mEvent.getReceivers().size() == 0) {
            Snackbar.make(contentET, getString(R.string.no_receiver_error), Snackbar.LENGTH_LONG).show();
        } else {

            if (mEvent.getIsActive()) {
                // isActive = true, set an Alarm
                Calendar calendar = Calendar.getInstance();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
                try {
                    calendar.setTime(sdf.parse(mEvent.getDateTime()));
                    setAlarm(mEvent.getId(), (int) mEvent.getRequestCode(), calendar.getTimeInMillis());
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }

            DatabaseReference mDatabaseReference = FirebaseDatabase.getInstance().getReference();

            FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
            if (firebaseUser != null) {
                showProgressDialog(getString(R.string.loading));
                mDatabaseReference.child("events")
                        .child(firebaseUser.getUid())
                        .child(mEvent.getId())
                        .setValue(mEvent).addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {

                        hideProgressDialog();

                        Intent eventDate = new Intent();
                        eventDate.putExtra("datetime", mEvent.getDateTime());
                        setResult(RESULT_OK, eventDate);
                        finish();
                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        hideProgressDialog();
                        setResult(RESULT_CANCELED, null);
                        finish();
                    }
                });
            }
        }
    }

    private Calendar getCalendar(RepeatMode repeatMode) {
        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.YEAR, Integer.parseInt(mYear));
        calendar.set(Calendar.MONTH, Integer.parseInt(mMonth) - 1);
        calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(mDay));
        calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(mHour));
        calendar.set(Calendar.MINUTE, Integer.parseInt(mMinute));
        calendar.set(Calendar.SECOND, 0);

        if (calendar.getTime().compareTo(new Date()) < 0) {
            return getNextExecuteTime(calendar, repeatMode);
        }
        return calendar;
    }

    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
        AppCompatSpinner spinner = (AppCompatSpinner) adapterView;
        if (spinner.getId() == R.id.weather_C_F) {
            switch (i) {
                case 0:
                    // 摄氏度
                    isCF = true;
                    break;
                case 1:
                    // 华氏度
                    isCF = false;
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {

    }

    @Override
    public void onConfirmChooseCity(LatLng ll, String locationName) {

        hideSoftKeyboard(receiverPhoneETV);
        chooseCityBTN.setText(locationName);
        lat = ll.latitude;
        lon = ll.longitude;
    }
}
